package cn.springcloud.fix.quartz.arithmetic;

import cn.springcloud.fix.quartz.dao.entity.SysJob;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class TaskAdapterComposite implements ArithmeticTaskAdapter {

    private final List<ArithmeticTaskAdapter> taskAdapterList = new LinkedList<>();

    private final Map<String, ArithmeticTaskAdapter> argumentResolverCache = new ConcurrentHashMap<>(32);

    public TaskAdapterComposite addAdapter(ArithmeticTaskAdapter adapter) {
        this.taskAdapterList.add(adapter);
        return this;
    }

    public TaskAdapterComposite addAdapters(@Nullable ArithmeticTaskAdapter... adapters) {
        if (adapters != null) {
            Collections.addAll(this.taskAdapterList, adapters);
        }
        return this;
    }

    public TaskAdapterComposite addAdapters(@Nullable List<? extends ArithmeticTaskAdapter> adapters) {
        if (adapters != null) {
            this.taskAdapterList.addAll(adapters);
        }
        return this;
    }

    public void clear() {
        this.taskAdapterList.clear();
    }

    public List<ArithmeticTaskAdapter> getTaskAdapterList() {
        return Collections.unmodifiableList(this.taskAdapterList);
    }

    @Override
    public boolean supportTask(String taskId) {
        return getArgumentResolver(taskId) != null;
    }

    @Override
    public void handleTask(SysJob sysJob) {
        ArithmeticTaskAdapter adapter = getArgumentResolver(sysJob.getId());
        Assert.notNull(adapter, "Unknown parameter type [" + sysJob.getId() + "]");
        adapter.handleTask(sysJob);
    }

    @Nullable
    private ArithmeticTaskAdapter getArgumentResolver(String taskId) {
        ArithmeticTaskAdapter result = this.argumentResolverCache.get(taskId);
        if (result == null) {
            for (ArithmeticTaskAdapter adapter : this.taskAdapterList) {
                if (adapter.supportTask(taskId)) {
                    result = adapter;
                    this.argumentResolverCache.put(taskId, result);
                    break;
                }
            }
        }
        return result;
    }
}
